﻿//
//  Copyright (c) 2009-2011 Liang Quan Qing.
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//  1. Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
//  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
//  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
//  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
//  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//  SUCH DAMAGE.
//

#ifndef FASTCONV_LOCAL_H_17BE643CA939D1EA16F1259B18D05DD6
#define FASTCONV_LOCAL_H_17BE643CA939D1EA16F1259B18D05DD6

#include <stddef.h>
#include "fastconv.h"

#if defined( _MSC_VER ) || defined( __BORLANDC__ )
#define INLINE __inline
#elif defined( __GNUC__ )
#define INLINE __inline__
#else
#define INLINE
#endif

#define CHARSET_TYPE_NONE               0
#define CHARSET_TYPE_SBCS               1
#define CHARSET_TYPE_MBCS               2
#define CHARSET_TYPE_DBCS               3
#define CHARSET_TYPE_UTF_8              4
#define CHARSET_TYPE_UTF_16LE           5
#define CHARSET_TYPE_UTF_16BE           6
#define CHARSET_TYPE_UTF_32LE           7
#define CHARSET_TYPE_UTF_32BE           8
#define CHARSET_TYPE_UTF_16             9
#define CHARSET_TYPE_UTF_32             10
#define CHARSET_TYPE_UTF_7              11

struct _supportName
{
    const char *    encodingName;
    unsigned int    index;
};

struct _fcnv_private_t
{
    const unsigned char*  pbToUniAreaTable;
    const unsigned short* pwToUniMapTable;
    const unsigned char*  pbFromUniAreaTable;
    const unsigned short* pwFromUniMapTable;
    unsigned int    csid;
    unsigned int    boUseDefaultChar;   //0: if cannot convert, return ERROR, 1: if cannot convert, replace by default character.
    WChar_t         DefaultWChar;       //default unicode char
    unsigned short  charsize;           //size of default char (ANSI)
    unsigned char   pDefaultChar[8];    //
    unsigned short  defaultUTF8Len;     //size of default UTF-8 char
    unsigned char   pDefalutUTF8[8];    //default UTF-8 char
};
typedef struct _fcnv_private_t priv_t;

typedef int (*InitFunc) (fcnv_t*  pfcnv);

typedef int (*ToUTF16Func)(
                    fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    WChar_t *   pBuffer,
                    size_t      destSizeInWChars);
typedef int (*FromUTF16Func)(
                    fcnv_t*     pfcnv,
                    const WChar_t* srcString,
                    size_t      srcSizeInWChars,
                    char *      pBuffer,
                    size_t      destSizeInBytes);

typedef int (*ToUTF8Func)(
                    fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    char *      pBuffer,
                    size_t      destSizeInBytes);
typedef int (*FromUTF8Func)(
                    fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    char *      pBuffer,
                    size_t      destSizeInBytes);

typedef int (*ToUTF32Func)(
                    fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    DChar_t *   pBuffer,
                    size_t      destSizeInDChars);
typedef int (*FromUTF32Func)(
                    fcnv_t*     pfcnv,
                    const DChar_t*srcString,
                    size_t      srcSizeInDChars,
                    char *      pBuffer,
                    size_t      destSizeInBytes);

typedef int (*mbtowcFunc)(fcnv_t* pfcnv, unsigned int * pdchar, const unsigned char* pmbchar, size_t count);
typedef int (*wctombFunc)(fcnv_t* pfcnv, unsigned char *pmbchar, unsigned int dchar);

struct _TFcnvFuncList
{
    InitFunc            init;
    ToUTF16Func         t16;
    FromUTF16Func       f16;
    ToUTF8Func          t8;
    FromUTF8Func        f8;
    ToUTF32Func         t32;
    FromUTF32Func       f32;
    fpGetFirstCharLen_t FirstCharLength;
    fpIsLeadByte_t      IsLeadByte;
    mbtowcFunc          mbtowc;
    wctombFunc          wctomb;
};
typedef struct _TFcnvFuncList funclist_t;

struct _fcnvDescInfo
{
    const char *    encodingName;
    unsigned int    minCharSize;
    unsigned int    maxCharSize;
    unsigned int    charsetType;
    const funclist_t *functions;
};
typedef struct _fcnvDescInfo    fcnvdesc_t;


#define isHighSurrogate(wch)    (( (wch) & 0xFC00 ) == 0xD800 )
#define isLowSurrogate(wch)     (( (wch) & 0xFC00 ) == 0xDC00 )
#define isSurrogate(wch)        (( (wch) & 0xF800 ) == 0xD800 )
#define SurrogateToDChar(high,low) (((((DChar_t)((high)&0x03FF))<<10)|((low)&0x03FF))+0x10000)

#define getHighSurrogate(dch)   (((((unsigned)((dch)-0x10000))>>10)&0x03FF)|0xD800)
#define getLowSurrogate(dch)    ((((unsigned)((dch)-0x10000))&0x03FF)|0xDC00)

#define isUTF8Style1(b1)                 ( ((b1)&0x80)==0 )
#define isUTF8Style2(b1,b2)              ( (((b1)&0xE0)==0xC0) && (((b2)&0xC0)==0x80) )
#define isUTF8Style3(b1,b2,b3)           ( (((b1)&0xF0)==0xE0) && (((b2)&0xC0)==0x80) && (((b3)&0xC0)==0x80) )
#define isUTF8Style4(b1,b2,b3,b4)        ( (((b1)&0xF8)==0xF0) && (((b2)&0xC0)==0x80) && (((b3)&0xC0)==0x80) && (((b4)&0xC0)==0x80) )
#define isUTF8Style5(b1,b2,b3,b4,b5)     ( (((b1)&0xFC)==0xF8) && (((b2)&0xC0)==0x80) && (((b3)&0xC0)==0x80) && (((b4)&0xC0)==0x80) && (((b5)&0xC0)==0x80) )
#define isUTF8Style6(b1,b2,b3,b4,b5,b6)  ( (((b1)&0xFE)==0xFC) && (((b2)&0xC0)==0x80) && (((b3)&0xC0)==0x80) && (((b4)&0xC0)==0x80) && (((b5)&0xC0)==0x80) && (((b6)&0xC0)==0x80) )

#define UTF8ToDCharS1(b1)                ( (DChar_t)(b1) )
#define UTF8ToDCharS2(b1,b2)             ( ((((DChar_t)(b1))&0x1F)<<6)  | (((DChar_t)(b2))&0x3F) )
#define UTF8ToDCharS3(b1,b2,b3)          ( ((((DChar_t)(b1))&0x0F)<<12) | ((((DChar_t)(b2))&0x3F)<<6) | (((DChar_t)(b3))&0x3F) )
#define UTF8ToDCharS4(b1,b2,b3,b4)       ( ((((DChar_t)(b1))&0x07)<<18) | ((((DChar_t)(b2))&0x3F)<<12) | ((((DChar_t)(b3))&0x3F)<<6) | (((DChar_t)(b4))&0x3F) )
#define UTF8ToDCharS5(b1,b2,b3,b4,b5)    ( ((((DChar_t)(b1))&0x03)<<24) | ((((DChar_t)(b2))&0x3F)<<18) | ((((DChar_t)(b3))&0x3F)<<12) | ((((DChar_t)(b4))&0x3F)<<6) | (((DChar_t)(b5))&0x3F) )
#define UTF8ToDCharS6(b1,b2,b3,b4,b5,b6) ( ((((DChar_t)(b1))&0x01)<<30) | ((((DChar_t)(b2))&0x3F)<<24) | ((((DChar_t)(b3))&0x3F)<<18) | ((((DChar_t)(b4))&0x3F)<<12) | ((((DChar_t)(b5))&0x3F)<<6) | (((DChar_t)(b6))&0x3F) )

DChar_t MixSurrogate(WChar_t first, WChar_t second, int *pValid);
unsigned GetU8CharSizeFromU32Char(DChar_t u32char);

void U32CharToU8Buff_1(DChar_t u32char, unsigned char* pbUtf8Buff, int* pUtf8len, int* pValid);
void U32CharToU8Buff_2(DChar_t u32char, unsigned char* pbUtf8Buff, int* pUtf8len, int* pValid);
void U8BuffToU32Char_1(const unsigned char* pbUtf8Buff, int* pUtf8len, DChar_t* pU32Char, int* pValid);
void U8BuffToU32Char_2(const unsigned char* pbUtf8Buff, int* pUtf8len, DChar_t* pU32Char, int* pValid);

INLINE unsigned short __btow(priv_t *pd, unsigned short ch)
{
    unsigned char idx;
    idx = pd->pbToUniAreaTable[(ch>>8)&0xff];
    if ( idx == 0xff )
        return 0xffff;
    return pd->pwToUniMapTable[idx*256 + (ch & 0xff)];
}

INLINE unsigned short __wtob(priv_t *pd, unsigned short ch)
{
    unsigned char idx;
    idx = pd->pbFromUniAreaTable[(ch>>8)&0xff];
    if ( idx == 0xff )
        return 0xffff;
    return pd->pwFromUniMapTable[idx*256 + (ch & 0xff)];
}

static int Null_init (fcnv_t* pfcnv);
static int Null_ToUTF16(fcnv_t* pfcnv, const char* srcString, size_t srcSizeInBytes, WChar_t * pBuffer, size_t destSizeInWChars);
static int Null_FromUTF16(fcnv_t* pfcnv, const WChar_t* srcString, size_t srcSizeInWChars, char * pBuffer, size_t destSizeInBytes);
static int Null_ToUTF8(fcnv_t* pfcnv, const char* srcString, size_t srcSizeInBytes, char * pBuffer, size_t destSizeInBytes);
static int Null_FromUTF8(fcnv_t* pfcnv, const char* srcString, size_t srcSizeInBytes, char * pBuffer, size_t destSizeInBytes);
static int Null_ToUTF32(fcnv_t* pfcnv, const char* srcString, size_t srcSizeInBytes, DChar_t * pBuffer, size_t destSizeInDChars);
static int Null_FromUTF32(fcnv_t* pfcnv, const DChar_t*srcString, size_t srcSizeInDChars, char * pBuffer, size_t destSizeInBytes);
static int Null_mbtowc(fcnv_t* pfcnv, unsigned int * pdchar, const unsigned char* pmbchar, size_t count);
static int Null_wctomb(fcnv_t* pfcnv, unsigned char *pmbchar, unsigned int dchar);
static int sbcs_mbtowcFunc(fcnv_t* pfcnv, unsigned int * pdchar, const unsigned char* pmbchar, size_t count);
static int sbcs_wctombFunc(fcnv_t* pfcnv, unsigned char *pmbchar, unsigned int dchar);
static int sbcs_getFirstCharLength(const char *s);
static int sbcs_isLeadByte(const char *s);
static int sbcs_t16(fcnv_t* pfcnv, const char* srcString, size_t srcSizeInBytes, WChar_t * pBuffer, size_t destSizeInWChars);
static int sbcs_f16(fcnv_t* pfcnv,const WChar_t* srcString,size_t srcSizeInWChars,char * pBuffer,size_t destSizeInBytes);
static int sbcs_t8(fcnv_t* pfcnv,const char* srcString,size_t srcSizeInBytes,char * pBuffer,size_t destSizeInBytes);
static int sbcs_f8(fcnv_t* pfcnv,const char* srcString2222,size_t srcSizeInBytes,char * pBuffer,size_t destSizeInBytes);
static int sbcs_t32(fcnv_t* pfcnv,const char* srcString,size_t srcSizeInBytes,DChar_t * pBuffer,size_t destSizeInDChars);
static int sbcs_f32(fcnv_t* pfcnv,const DChar_t*srcString,size_t srcSizeInDChars,char * pBuffer,size_t destSizeInBytes);
static int dbcs_mbtowcFunc(fcnv_t* pfcnv, unsigned int * pdchar, const unsigned char* pmbchar, size_t count);
static int dbcs_wctombFunc(fcnv_t* pfcnv, unsigned char *pmbchar, unsigned int dchar);
static int dbcs_t16(fcnv_t* pfcnv, const char* srcString, size_t srcSizeInBytes, WChar_t * pBuffer, size_t destSizeInWChars);
static int dbcs_f16(fcnv_t* pfcnv,const WChar_t* srcString,size_t srcSizeInWChars,char * pBuffer,size_t destSizeInBytes);
static int dbcs_t8(fcnv_t* pfcnv,const char* srcString,size_t srcSizeInBytes,char * pBuffer,size_t destSizeInBytes);
static int dbcs_f8(fcnv_t* pfcnv,const char* srcString2222,size_t srcSizeInBytes,char * pBuffer,size_t destSizeInBytes);
static int dbcs_t32(fcnv_t* pfcnv,const char* srcString,size_t srcSizeInBytes,DChar_t * pBuffer,size_t destSizeInDChars);
static int dbcs_f32(fcnv_t* pfcnv,const DChar_t*srcString,size_t srcSizeInDChars,char * pBuffer,size_t destSizeInBytes);



#endif  //FASTCONV_LOCAL_H_17BE643CA939D1EA16F1259B18D05DD6

